package club.emergency.wechat.ranking.operate.provider.impl;

import club.emergency.wechat.common.response.ResponseEntity;
import club.emergency.wechat.common.response.StatusCode;
import club.emergency.wechat.ranking.operate.RankingOperate;
import club.emergency.wechat.redis.common.RedisKeyConstant;
import lombok.extern.slf4j.Slf4j;
import net.javacrumbs.shedlock.core.SchedulerLock;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

/**
 * Create with IntelliJ IDEA
 * Project Name: wechat
 * Package Name: club.emergency.wechat.ranking.operate.provider.impl
 * Date: 2019/2/25
 *
 * @author: 快乐的小菌菌
 * Description:
 */
@Slf4j
@RestController
public class RankingOperateImpl implements RankingOperate {

    private StringRedisTemplate stringRedisTemplate;

    public RankingOperateImpl(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public String incrementScore(@RequestParam("staffId") Long staffId, @RequestParam("score") Integer score) {
        ZSetOperations<String, String> stringStringZSetOperations = stringRedisTemplate.opsForZSet();
        SessionCallback<Object> sessionCallback = new SessionCallback<Object>() {
            @Override
            public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
                try {
                    redisOperations.multi();
                    stringStringZSetOperations.incrementScore(RedisKeyConstant.RANKING, String.valueOf(staffId), score.doubleValue());
                    return redisOperations.exec();
                } catch (Exception e) {
                    redisOperations.discard();
                    throw new RuntimeException(e);
                }
            }
        };
        try {
            stringRedisTemplate.execute(sessionCallback);
            return ResponseEntity.ok(StatusCode.REDIS_SAVE_OK, "叠加用户分数成功！");
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseEntity.ok(StatusCode.REDIS_SAVE_ERROR, "叠加用户分数失败！");
        }
    }

    @Scheduled(cron = "0 0 0,6,12,18 * * ?")
    @SchedulerLock(name = "shedLock_refreshRankingCache")
    public void refreshRankingCache() {
        stringRedisTemplate.delete(RedisKeyConstant.RANKING_CACHE);
    }

    @Scheduled(cron = "0 0 0 1 * ?")
    @SchedulerLock(name = "shedLock_refreshRanking")
    public void refreshRanking() {
        stringRedisTemplate.delete(RedisKeyConstant.RANKING);
    }
}
